跳到主要内容

Vue基本用法

前置知识

什么是Vue

中文官网 Vue是一种渐进式JavaScript框架

声明式渲染 -> 组件系统 -> 客户端路由 -> 集中式状态管理 -> 项目构建
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<!-- 引入 axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 引入 qs -->
<script src="https://cdn.bootcss.com/qs/6.5.1/qs.min.js"></script>
const qs = Qs // 引入QS库把请求参数转成表单形式
axios.defaults.timeout = 3000; // 设置超时时间
// 设置请求的基准URL地址
axios.defaults.baseURL = 'http://localhost:8080/';
// 使请求可以携带 Cookie
axios.interceptors.request.use(config => {
config.withCredentials = true;
return config;
});

new Vue({
el: '#app',
data() {
return {
username: '',
password: ''
}
},
methods: {
login() {
axios.post('/login', qs.stringify({
username: this.username,
password: this.password
}), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then((result) => {
console.log(result);
}).catch((err) => {
console.log(err);
});
}
},
})

生命周期(钩子函数)

Vue的生命周期Nonuz6.png

其中红色部分都是可以插入钩子的地方

参考自官方文档

  • 挂载(初始化相关属性)
时期作用
beforeCreate在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
create在实例创建完成后被立即调用。$el 属性 还尚不可用
beforeMount在挂载开始之前被调用:相关的 回调函数 首次被调用。
mounted实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。并挂载到实例上去之后调用该钩子
  • 更新(元素或组件的变更操作)
时期作用
beforeUpdate数据更新时调用,发生在虚拟 DOM 打补丁之前。
update由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。(数据已经更新了)
  • 销毁(销毁相关属性)
时期作用
beforeDestroy实例销毁之前调用。在这一步,实例仍然完全可用。
destroy实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。

什么是MVVM

原本的 MVC 是以下的模式

NgZa0U.png

而 MVVM 是 MVC 的一种变体

M:Model V:View VM:ViewModel

NgW1pT.png

在MVVM架构里是不允许数据和视图直接通信的,只能通过ViewModel来通信,而ViewModel就是定义了一个Observer观察者

  • ViewModel能够观察到数据的变化,并对视图对应的内容进行更新
  • ViewModel能够监听到视图的变化,并能够通知数据发生改变

实际上就是类似于AndroidStudio那样的数据绑定机制,亦或者说类似于Spring的IOC概念意义,在需要数据的地方使用ViewModel,从而方便传入数据,而无需手动的传入数据

vue各版本的区别

# 压缩后的代码
vue.min.js
# 可看的源码(开发版,有完整的提示信息)
vue.js

vue主要的属性

el 挂载点

el 挂载点 用来绑定 DOM,Vue 会管理 el 选择命中的元素及其内部的后代元素 使用的语法和 css 是一样的,但是注意不可以在 body 和 html 标签上使用,但是可以挂载在其他的元素上

<div id="app"></div>
<script>
let vm = new Vue({
el: '#app'
})
</script>

data 数据

用来填充数据,data 中可以写复杂类型的数据(数组,对象等) 渲染复杂类型数据时,遵守 JS 的语法即可 要读取数据就直接读取 data 里的属性就好了

<script>
let vm = new Vue({
el: '#app',
data: {
type: 'A'
},
})
</script>

method

这里面写绑定的方法

<body>
<div id="app">
<button v-on:click="sayhell">click this</button>
<!-- 或者直接调用 -->
{{sayhell()}}
</div>

<script src="/node_modules/vue/dist/vue.min.js"></script>
<script>
let vm = new Vue({
el: '#app',
methods: {
sayhell: function () {
console.log('hello');
}
},
})
</script>
</body>

内容绑定,事件绑定

v-text 插入文本

设置标签的文本值(textContent) 简写就是{{msg}}

<div id='app'>
<h2 v-text="message + '这是字符串拼接'"></h2>
</div>
let app = new Vue({
el:'#app',
data: {
message: 'hello vue'
}
})

实际上直接用{{msg}}也可以

<div id='app'>
<h2>
{{message + "这是字符串拼接"}}
</h2>
</div>

v-html 插入标签

设置标签的innerHTML 如果只是插入普通文本则与上面的v-text属性没有区别,但是插入标签的话必须用这个v-html否则解析不出来

<div id='app'>
<p v-html="message"></p>
</div>
let app = new Vue({
el:'#app',
data: {
message: '<h1>hello vue </h1>'
}
})

v-on 绑定事件

为元素绑定事件(就是监听事件)

语法:

<div id='app'>
<input type="button" value="按钮名称" v-on:事件名="方法">
</div>

v-on可以简写使用 @ 字符 例如

<input type="button" value="按钮名称" @click="方法">
let app = new Vue({
el:'#app',
data: {
food: '西兰花'
},
methods: {
方法: function(){
/**
如果想在方法里修改某些属性值则使用this指针,
因为本质上一个Vue就是一个对象,所以通过this指针来提高作用域
Vue里的this有点特殊,后面讲
*/
this.food = '青瓜'
}
}
})

常用的事件: 事件名 | 作用 ---------|---------- click | 点击 monseenter | 鼠标移动 dblclick | 鼠标双击

官网 事件参考jQuery的

参数:event

用在普通元素上时,只能监听原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。

综合案例:计数器

<div id='app'>
<button @click="add">+</button>
<span>{{number}}</span>
<button @click="sub">-</button>
</div>
let app = new Vue({
el:'#app',
data: {
number: 0
},
methods: {
add:function(){
this.number++
},
sub:function(){
this.number--
}
},
})

显示切换,属性绑定

v-show 显示和隐藏

根据表达值的真假,切换元素的显示和隐藏

<div id='app'>
<button @click="show">显示/隐藏</button>
<h1 v-show="isShow">看得见这句话吗?</h1>
</div>

原理是通过css来隐藏的

<h1 style="display: none;">看得见这句话吗?</h1>
let app = new Vue({
el:'#app',
data: {
isShow: false
},
methods: {
show:function(){
this.isShow = !this.isShow
}
},
})

v-if 显示和隐藏

根据表达值的真假,切换元素的显示和隐藏(操纵dom元素)

语法与上基本一致,只是把show改成了if,与上面的区别就是show是通过改css样式来隐藏的,而if是直接从dom树里剔除掉这个元素

所以频繁切换的元素用上面那个v-show,因为操纵dom树对性能的消耗较大

<div id='app'>
<button @click="show">显示/隐藏</button>
<h1 v-show="isShow">看得见这句话吗?</h1>
</div>
let app = new Vue({
el:'#app',
data: {
isShow: false
},
methods: {
show:function(){
this.isShow = !this.isShow
}
},
})

除了if还可以使用else属性来完成逻辑判断

<div id="app">
<h1 v-if="type==='A'">YES</h1>
<h1 v-else-if="type==='B'">NO</h1>
<h1 v-else>WOW</h1>
</div>

<script src="/node_modules/vue/dist/vue.min.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
type: 'A'
},
})
</script>

v-bind 绑定属性

参考官方的v-bind

用来设置元素的属性,比如src、title、class

语法 v-bind:属性名=表达式 缩写::属性名=表达式

<div id='app'>
<button @click="change">更改图片地址</button>
<img v-bind:src="imageSrc"
:title=" 'this is image ' + imageTitle"
:class="{active:isActive}">
</div>

{active:isActive} 当isActive等于true时class的值为active否则为空

let app = new Vue({
el:'#app',
data: {
imageSrc: 'https://image.alsritter.icu/2020/06/19/NuPrVJ.jpg',
imageTitle: '标题',
isActive: true
},
methods: {
change:function(){
this.imageSrc = 'https://image.alsritter.icu/2020/06/19/NuP226.jpg'
}
},
})

v-bind 绑定样式

方式一

实际上和上面的那个用法是基本一致的,只是动态的更改class的内容来动态更换css

.active {
height: 100px;
width: 100px;
border: 1px solid red;
}

.change {
background-color: blueviolet;
}
<!-- 这里的 {active: isActive , change: isChange} 和上面绑定属性的那个用法是一样的-->
<div id="app">
<div :class="{active: isActive , change: isChange}"></div>
<button @click='show'>显示方块</button>
<button @click='handle'>改变颜色</button>
</div>
let vm = new Vue({
el: '#app',
data: {
isActive: true,
isChange: false
},
methods: {
show: function(){
this.isActive = !this.isActive
},
handle: function(){
this.isChange = !this.isChange
}
},
})

方式二

除了上面那种直接绑定对象的方式,还可以使用标签的style属性

<div :style="{border: borderStyle , width: widthStyle , height: heightStyle}"></div>

方式三

最后还有一种直接传递对象到style属性的形式,注意上面的是花括号,这里是中括号

<div :style="[objStyle, obj2Style]"></div>

在vue的data区里加上

data:{
objStyle:{
border: '1px solid red',
width: '100px',
height: '100px'
},
obj2Style:{
...
}
}

综合案例:切换图片

参考自黑马--本地应用-图片切换

<div id='app'>
<button @click="last">上一张</button>
<img v-bind:src="imageSrc[index]" style="width: 300px;">
<button @click="next">下一张</button>
</div>
let app = new Vue({
el: '#app',
data: {
imageSrc: [
'https://image.alsritter.icu/2020/06/19/Nu9RF1.jpg',
'https://image.alsritter.icu/2020/06/19/Nu9goR.jpg',
'https://image.alsritter.icu/2020/06/19/NuPfKO.jpg',
'https://image.alsritter.icu/2020/06/19/NuP226.jpg',
'https://image.alsritter.icu/2020/06/19/NuPsa9.jpg'
],
index: 0
},
methods: {
last: function () {
this.index <= 0 ? this.index:this.index--
},
next: function () {
this.index >= (this.imageSrc.length - 1) ? this.index : this.index++
}
},
})

列表循环,表单元素绑定

v-for 循环语句

官方文档--list

使用有两种形式

<div id="app">
<!-- 第一种形式 -->
<li v-for="item in items">
{{item.message}}
</li>

<!-- 第二种形式 -->
<li v-for="(item, index) in items" :key="index">
{{items[index].message}}
</li>
</div>

vue循环的不是自身,而是包含了 item 的子标签

let vm = new Vue({
el: '#app',
data: {
items: [
{message: '项目一'},
{message: '项目二'},
{message: '项目三'}
]
},
})

key的作用:帮助Vue区分不同的元素,从而提高性能,原理就是为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素(就是当数据变更时无需重新循环),需要为每项提供一个唯一 key

所以尽可能的在使用 v-for 时提供 key

<li v-for="(item, index) in items" :key="index.id">{{item}} + '----' {{index}}</li>

v-on补充

传递自定义参数,事件修饰符 参考自官方文档 用法 案例参考黑马教程

传递参数

例:

<div id='app'>
<button @click="test('小明','小美')">测试v-on事件修饰符</button>
</div>
let app = new Vue({
el: '#app',
methods: {
test: function (p1,p2) {
console.log(`hi ${p1}${p2}`)
}
},
})

事件修饰符

就是事件的后面跟上 .修饰符 可以对事件进行限制

事件修饰符更多用法参考官方文档的--事件修饰符

.once

.once 只有在第一次点击时会执行,再次点击不会起作用

<div v-on:click.once='alert("1")'></div>

.stop

.stop - 调用 event.stopPropagation()。阻止函数的传递 当出现下面这种情况时 点击子级的div会,先弹出2,再弹出1

<div v-on:click='alert("1")' style="width: 100%;height: 45px;background-color: black;">
<div v-on:click="alert('2')" style='width: 80%;margin-left: 10%;background-color: white;'>
123
</div>
</div>

加上.stop 之后 就只会弹出2,不会弹出1 了

<div v-on:click.stop="alert('2')" style='width: 80%;margin-left: 10%;background-color: white;'>
123
</div>

.prevent

.prevent - 调用 event.preventDefault()。 就是阻止默认程序,比如form表单中的summit提交按钮,会自己提交,加上之后 直接不让提交了,也不跳转,只是执行自己命名的函数

<input type="submit" value="提交" @click.prevent="handle">

.capture 和 .self

这两个参考 vue中的.capture和.self区分,初步理解 .capture - 添加事件侦听器时使用 capture 模式。 .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。

按键修饰符

按键修饰符更多用法参考官方文档的--按键修饰符

.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。(就是监听按键) 这个.{keyCode | keyAlias}使用例:

<!-- 这样按下回车(enter)就会执行这个sayHi函数 -->
<input type="text" @keyup.enter="sayHi">

<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

鼠标修饰符

.left - (2.2.0) 只当点击鼠标左键时触发。 .right - (2.2.0) 只当点击鼠标右键时触发。 .middle - (2.2.0) 只当点击鼠标中键时触发。 .passive - (2.3.0) 以 { passive: true } 模式添加侦听器




v-model 双向绑定

获取和设置表单元素的值(双向数据绑定)

<div id="app">
<input type="text" v-model="message"> {{message}}
</div>
let vm = new Vue({
el: '#app',
data: {
message: "12345"
}
})

绑定下拉框

注意:如果v-model表达式的初始值未能匹配任何选项,<select>元素会被渲染为未选择状态 在ios中,这会使用户无法选择第一个选项。因为这样的情况下,IOS不会触发change事件,所以最好在顶部加上一个值为空的禁选项

<div id="app">
<select v-model="message">
<option value="" disabled>请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>

{{message}}
</div>
let vm = new Vue({
el: '#app',
data: {
message: ""
}
})

表单域修饰符

  • number:转化为数值
  • trim:去掉开始和结尾的空格
  • lazy:将input事件切换为change事件,就是原本的事件时输入时就触发,而lazy是当失去焦点时才触发(例如注册时验证用户名是否被占用时就很有用)

例如:将字符型转化为number

<div id="app">
<input type="number" v-model.number="age">
<button @click="handle">点击</button>
</div>

测试代码

let vm = new Vue({
el: '#app',
data: {
age: ''
}, methods: {
handle: function () {
console.log(this.age + 100)
}
},
})

表单操作

基于Vue的表单操作 ,就以下面的例子来参考如何绑定表单中的元素

  • input 单行文本
  • textarea 多行文本
  • select 下拉多选
  • radio 单选框
  • checkbox 多选框

使用的测试表单

<div id="app">
<form action="#" method="POST">
<div>
<span>姓名:</span><input type="text" v-model="uname">
</div>

<div>
<span>性别:</span>
<!-- 这里的label标签的作用就是点击label标签的文本后,光标跳转到for属性中id所对应的标签处 -->
<input type="radio" id="male" name="sex" value="1" v-model="gender">
<label for="male"></label>
<input type="radio" id="female" name="sex" value="2" v-model="gender">
<label for="female"></label>
</div>

<div>
<span>爱好:</span>
<!-- 因为本来就不用默认表单提交,所以可以不设置name,
上面的radio设置name是为了防止多选,这个本来就是多选框,所以随意了
且注意:多选框的data要设置成数组 [] -->
<input type="checkbox" id="ball" v-model="hobby" value="1" >
<label for="ball">篮球</label>
<input type="checkbox" id="sing" v-model="hobby" value="2">
<label for="sing">唱歌</label>
<input type="checkbox" id="code" v-model="hobby" value="3">
<label for="code">敲代码</label>
</div>

<div>
<span>职业:</span>
<!-- 如果想要多选则加上multiple属性 (multiple="true"),按shift就能多选了 -->
<select v-model="occupation">
<option disabled value="0">请选择职业</option>
<option value="1">教师</option>
<option value="2">程序员</option>
<option value="3">学生</option>
<option></option>
</select>
</div>

<div>
<span>个人简历:</span>
<!-- 这个多行文本绑定和单行文本差不多
描述的单词: description 缩写 desc -->
<textarea cols="30" rows="10" v-model="desc"></textarea>
</div>

<div>
<input type="submit" value="提交" @click.prevent="handle">
</div>
</form>
</div>
let vm = new Vue({
el: '#app',
data: {
uname: 'alsritter',
gender: 1,
hobby: [],
occupation: 0,
desc: ""
},methods: {
handle: function(){
console.log(this.uname)
}
},
})